package com.yonyou.crm.common.dao.imp;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Repository;

import com.yonyou.crm.common.dao.itf.IBaseDao;
import com.yonyou.crm.common.page.entity.Page;
import com.yonyou.iuap.context.InvocationInfoProxy;


@Repository("baseDao")
public class BaseDaoImpl implements IBaseDao{

	@Resource(name = "crmSqlSession")  
    protected SqlSessionTemplate crmSqlSession;  
	
	@Resource(name = "crmSqlSession")  
    protected SqlSessionTemplate crmSlaveSqlSession;  
	
	/**
	 * 根据实体获取StatementID
	 * @param clazz
	 * @param prefix
	 * @return
	 */
	protected <T> String getStatement(Class<T> clazz, String prefix) {  
        String entityName = clazz.getSimpleName();  
        if (entityName.endsWith("DO") || entityName.endsWith("VO")) {  
            entityName = entityName.substring(0, entityName.length() - 2);  
        }  
        String nameSpace=clazz.getPackage().getName()+"."+entityName+"Mapper";
        return nameSpace + "." + prefix + entityName;  
    }
	
	/**
	 * 根据方法名和实体获得StatementID
	 * @param clazz
	 * @param funcName
	 * @return
	 */
	protected <T> String getCustomStatement(Class<T> clazz, String funcName) {  
		
		String entityName = clazz.getSimpleName();
        if (entityName.endsWith("DO") || entityName.endsWith("VO")) {  
            entityName = entityName.substring(0, entityName.length() - 2);
        }
        
        return clazz.getPackage().getName() + "." + entityName + "Mapper" + "." + funcName;
    }
	
	@Override
	public <T extends Serializable> T save(T vo) {
		String statement = getStatement(vo.getClass(), "insert");  
       	crmSqlSession.insert(statement, vo); 
       	return vo;
	}

	@Override
	public <T extends Serializable> int delete(T vo) {
		String statement = getStatement(vo.getClass(), "delete");
        return crmSqlSession.update(statement, vo);
	}
	
	@Override
	public <T extends Serializable> int batchDelete(Class<T> clazz, Object ids) {
		String statement = getStatement(clazz, "batchDelete");
		Map<String, Object> paraMap = new HashMap<String, Object>();
		paraMap.put("ids", ids);
		paraMap.put("deletedUserId", new Long(InvocationInfoProxy.getParameter("id")));
		paraMap.put("deletedTime", new Date());
        return crmSqlSession.update(statement, paraMap);
	}
	
	@Override
	public <T extends Serializable> int delete(Class<T> clazz , String funcName, Map<String, Object> paraMap) {
		if (paraMap != null) {
			paraMap.put("deletedUserId", new Long(InvocationInfoProxy.getParameter("id")));
			paraMap.put("deletedTime", new Date());
		}
        return crmSqlSession.update(getCustomStatement(clazz, funcName), paraMap);
	}
	
	@Override
	public <T extends Serializable> T update(T vo) {
		String statement = getStatement(vo.getClass(), "update");  
		crmSqlSession.update(statement, vo);
		return vo;
	}
	
	@Override
	public <T extends Serializable> T getById(Class<T> clazz, Serializable id) {
		String statement = getStatement(clazz, "idGet");  
        return crmSlaveSqlSession.selectOne(statement, id);
	}
	
	/** 
     *  
     * 组装排序串 
     *  
     * @param sort 
     * @param order  最好将order定义成枚举类型，传递一个枚举数组 
     * @return 
     */  
	private String genOrderStr(String sort, String order) {
		
		String orderBy = "";
		if (StringUtils.isNotBlank(sort)) {
			if (StringUtils.isNotBlank(order)) {
				StringBuilder sb = new StringBuilder(" ");
				String[] aSort = sort.split(",");
				String[] aOrder = order.split(",");
				for (int i = 0; i < aSort.length; i++) {
					sb.append(aSort[i]).append(" ");
					if (i < aOrder.length) {
						sb.append(aOrder[i]).append(",");
					} else {
						sb.append("ASC").append(",");
					}
				}
				// 删除最后一个,
				sb.deleteCharAt(sb.length() - 1);
				orderBy = sb.toString();

			} else {
				orderBy = " order by " + sort;
			}
		}
		return orderBy;
	}
	
	@Override
	public <T extends Serializable> Page<T> pageSelect(Class<T> clazz,
			Page<?> p, String[] attrs, Object[] values) {
		
        Map<String, Object> paraMap = new HashMap<String, Object>();  
  
        if (values != null && attrs != null) {  
            for (int i = 0; i < values.length; i++) {  
                if (i < attrs.length) {  
                    paraMap.put(attrs[i], values[i]);  
                }  
  
            }  
        }  
        
        Page<T> responsePage = new Page<T> ();
        String statement = getStatement(clazz, "page");  
        if (p != null) {
        	int startNum = p.getStartIndex();  
            int pageSize = p.getPageSize();  
            paraMap.put("startNum", startNum);  
            paraMap.put("pageSize", pageSize);  
            paraMap.put("endNum", startNum + pageSize);  
            
            responsePage.setPage(p.getPage());
            responsePage.setPageSize(p.getPageSize());
            responsePage.setTotal(pageCount(clazz, attrs, values)); 
        }
        
        List<T> list = crmSlaveSqlSession.selectList(statement,  
                paraMap);  
        responsePage.setData(list);
        
        return responsePage;
	}
	
	@Override
	public <T extends Serializable> Page<T> pageSelect(Class<T> clazz,
			Page<?> p, String selectFuncName, String countFuncName, Map<String, Object> paraMap) {

		 Page<T> responsePage = new Page<T> ();
		 if (p != null) {
			 
        	int startNum = p.getStartIndex();  
            int pageSize = p.getPageSize();  
        	paraMap.put("startNum", startNum);
            paraMap.put("pageSize", pageSize);
            paraMap.put("endNum", startNum + pageSize);
            
            responsePage.setPage(p.getPage());
            responsePage.setPageSize(p.getPageSize());
            responsePage.setTotal(countAll(clazz, countFuncName, paraMap));
	    }
  
       
        List<T> list = crmSlaveSqlSession.selectList(getCustomStatement(clazz, selectFuncName),  
                paraMap);  
        responsePage.setData(list);
        return responsePage;
	}

	@Override
	public <T extends Serializable> int pageCount(Class<T> clazz,
			String[] attrs, Object[] values) {
		
		Map<String, Object> paraMap = new HashMap<String, Object>();  
        if (values != null && attrs != null) {  
            for (int i = 0; i < values.length; i++) {  
                if (i < attrs.length) {  
                    paraMap.put(attrs[i], values[i]);  
                }  
            }  
        }  
        String statement = getStatement(clazz, "pageCount");  
        Object o = crmSlaveSqlSession.selectOne(statement,paraMap);  
        return Integer.parseInt(o.toString()); 
	}
	
	@Override
	public <T extends Serializable> int countAll(Class<T> clazz) {
		String statement = getStatement(clazz, "count");  
        Object o = crmSlaveSqlSession.selectOne(statement);  
        return Integer.parseInt(o.toString()); 
	}
	
	@Override
	public <T extends Serializable> int countAll(Class<T> clazz, String funcName, Object param) {
        Object o = crmSlaveSqlSession.selectOne(getCustomStatement(clazz, funcName), param);
        return Integer.parseInt(o.toString());
	}
	
	
	@Override
	public <T extends Serializable> T selectOne(Class<T> clazz, String funcName, Object param) {
		return crmSlaveSqlSession.selectOne(getCustomStatement(clazz, funcName),param); 
	}

	@Override
	public <T extends Serializable> Object selectOne(Class<T> clazz,String funcName) {
		return crmSlaveSqlSession.selectOne(getCustomStatement(clazz, funcName)); 
	}
	
	@Override
	public <T extends Serializable> List<Map<String, Object>> selectList(Class<T> clazz, String funcName, Object param) {
		return crmSlaveSqlSession.selectList(getCustomStatement(clazz, funcName), param); 
	}

	@Override
	public <T extends Serializable> List<String> selectStrList(Class<T> clazz, String funcName, Object param) {
		return crmSlaveSqlSession.selectList(getCustomStatement(clazz, funcName), param);
	}
	
	@Override
	public <T extends Serializable> List<Map<String, Object>> selectList(Class<T> clazz, String funcName) {
		return crmSlaveSqlSession.selectList(getCustomStatement(clazz, funcName)); 
	}
	
	@Override
	public <T extends Serializable> List<T> selectVoList(Class<?> clazz, String funcName, Object param) {
		return crmSlaveSqlSession.selectList(getCustomStatement(clazz, funcName), param); 
	}

	@Override
	public <T extends Serializable> int updateSql(Class<T> clazz, String funcName, Object param) {
		return crmSqlSession.update(getCustomStatement(clazz, funcName), param);
	}

	@Override
	public <T extends Serializable> int updateSql(Class<T> clazz, String funcName) {
		return crmSqlSession.update(getCustomStatement(clazz, funcName));
	}

	@Override
	public <T extends Serializable> int deleteSql(Class<T> clazz, String funcName, Object param) {
		return crmSqlSession.delete(getCustomStatement(clazz, funcName), param);
	}

	@Override
	public <T extends Serializable> int deleteSql(Class<T> clazz, String funcName) {
		return crmSqlSession.delete(getCustomStatement(clazz, funcName));
	}
	
	@Override
	public <T extends Serializable> int saveSql(Class<T> clazz, String funcName, Object param) {
		return crmSqlSession.insert(getCustomStatement(clazz, funcName), param);
	}

}
